using GameBaseFramework.Base;
using GameBaseFramework.Patterns;
using streaming;
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;

namespace GameBaseFramework.Pattern
{
    /// <summary>
    /// 指令管理器，单例模式
    /// </summary>
    public static class CommandManager
    {
        /// <summary>
        /// 指令的唯一索引
        /// </summary>
        private static int uniqueIndex = 0;

        /// <summary>
        /// 所有指令链表
        /// </summary>
        private static LinkedList<Command> CommandList = new();

        /// <summary>
        /// 具有Icommand接口的实体到回调的映射，即接收器身上的委托
        /// </summary>
        private static Dictionary<Icommand, LinkedList<Delegate>> IcommandDic = new();

        /// <summary>
        /// Command类到回调的映射，即Command对应的回调
        /// </summary>
        private static Dictionary<int, LinkedList<Delegate>> IntDic = new();



        #region Private方法

        /// <summary>
        /// 处理指令
        /// </summary>
        private static void HandleCommand<T>(T command) where T:Command
        {
            var TypeID = TypeId.GetId<T>();
            if (IntDic.TryGetValue(TypeID, out var list))
            {
                var Current = list.First;
                while (Current != null)
                {
                    try
                    {
                        Current.Value.DynamicInvoke(command);
                    }
                    catch (Exception e)
                    {
                        DebugTool.LogException(e);
                    }
                    Current = Current.Next;
                }
            }
        }
        #endregion


        #region 公共扩展方法

        /// <summary>
        /// 添加指令
        /// </summary>
        /// <param name="self"></param>
        /// <param name="command"></param>
        public static void SendCommand<T>(this Icommand self, T command) where T : Command
        {
            command.TypeId = TypeId.GetId<T>();
            if (command.SyncExecute)
            {
                HandleCommand(command);
            }
            else
            {
                command.Index = ++uniqueIndex;
                var CurCommand = CommandList.First;
                while (CurCommand != null)
                {
                    if (CurCommand.Value.Priority < command.Priority)
                    {
                        CommandList.AddBefore(CurCommand, command);
                        return;
                    }
                    CurCommand = CurCommand.Next;
                }
                CommandList.AddLast(command);
            }
        }

        /// <summary>
        /// 添加指令（匿名对象）
        /// </summary>
        /// <param name="self"></param>
        /// <param name="command"></param>
        public static void SendCommand<T>(T command) where T : Command
        {
            command.TypeId = TypeId.GetId<T>();
            if (command.SyncExecute)
            {
                HandleCommand(command);
            }
            else
            {
                command.Index = ++uniqueIndex;
                var CurCommand = CommandList.First;
                while (CurCommand != null)
                {
                    if (CurCommand.Value.Priority < command.Priority)
                    {
                        CommandList.AddBefore(CurCommand, command);
                        return;
                    }
                    CurCommand = CurCommand.Next;
                }
                CommandList.AddLast(command);
            }
        }

        /// <summary>
        /// 添加回调
        /// BindCommand时同时添加两种Dic中的回调
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="self"></param>
        /// <param name="command"></param>
        /// <param name=""></param>
        public static void BindCommand<T>(this Icommand self, Action<T> Handler) where T : Command
        {
            if (Handler == null) return;
            Debug.Log($"Command : {TypeId.GetId<T>()} => BindCommand");

            //处理IcommandDic
            if (!IcommandDic.TryGetValue(self, out var Handlers))
            {
                Handlers = new LinkedList<Delegate>();
                Handlers.AddLast(Handler);
                IcommandDic.Add(self, Handlers);
            }
            else if (!Handlers.Contains(Handler))
            {
                Handlers.AddLast(Handler);
            }

            //处理CommandTypeIDDic
            var commandTypeID = TypeId.GetId<T>();
            if (!IntDic.TryGetValue(commandTypeID, out var delegates))
            {
                delegates = new LinkedList<Delegate>();
                IntDic.Add(commandTypeID, delegates);
            }
            delegates.AddLast(Handler);

        }

        /// <summary>
        /// 解绑自身指定回调
        /// 基本限定了非Lambda表达式才能使用
        /// </summary>
        /// <param name="self"></param>
        public static void UnbindCommand<T>(this Icommand self, Action<T> handler) where T:Command
        {
            var commandTypeID = TypeId.GetId<T>();
            if (IntDic.TryGetValue(commandTypeID, out var list))
            {
                list.Remove(handler);
            }

        }

        /// <summary>
        /// 解绑自身所有指令
        /// </summary>
        /// <param name="self"></param>
        public static void UnBindAllSelfCommands(this Icommand self)
        {
            Dictionary<int, Delegate> typeIDToRemove = new();

            //删除IcommandDic的对应指令
            if (IcommandDic.TryGetValue(self, out var delegates))
            {
                foreach (var @delegate in delegates)
                {
                    foreach (var list in IntDic)
                    {
                        if (list.Value.Remove(@delegate))
                        {
                            typeIDToRemove.Add(list.Key, @delegate);
                        }
                    }
                }
                IcommandDic.Remove(self);
            }

            //删除IntDic的对应指令
            foreach (var i in typeIDToRemove)
            {
                IntDic[i.Key].Remove(i.Value); 
            }
        }

        /// <summary>
        /// Tick驱动
        /// 每帧执行缓存的命令
        /// </summary>
        public static void Update()
        {
            if (CommandList.Count >0)
            {
                var CurrentCommand = CommandList.First;
                while (CurrentCommand != null)
                {
                    try
                    {
                        HandleCommand(CurrentCommand.Value);
                    }
                    catch (Exception e)
                    {
                        DebugTool.LogException(e);
                    }
                    CurrentCommand = CurrentCommand.Next;
                }
                CommandList.Clear();
            }
        }
        #endregion

    }





}
